/*
 *
 *   Copyright (C) 2005 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include "download_list_view.h"
#include "state_icons.h"
#include <urlglib/download_node.h>
#include <urlglib/ug_i18n.h>

static gchar* dtoa_unit (double d, gchar* tail_str)
{
	const static gchar* unit_str[4] = {"", " KB", " MB", " GB"};
	guint  index;
	gint   precision = 0;

	for (index=0; index < 3; index++) {
		if (d > 1024.0) {
			d /= 1024.0;
			precision = 2;
		}
		else
			break;
	}

	return g_strdup_printf ("%.*f%s%s", precision, d, unit_str[index], tail_str);
}

// data set function for GtkCellRenderer ----------------------------
static void col_set_icon (GtkTreeViewColumn *tree_column,
                          GtkCellRenderer   *cell,
                          GtkTreeModel      *model,
                          GtkTreeIter       *iter,
                          gpointer           data)
{
	DownloadNode* dnode;
	int  state;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);
	state = dnode->state;

	if (state >= STATE_N_ICONS)
		state = STATE_ICON_ERROR;

	g_object_set (cell, "pixbuf", state_icons[state], NULL);
}

static void col_set_filename (GtkTreeViewColumn *tree_column,
                              GtkCellRenderer   *cell,
                              GtkTreeModel      *model,
                              GtkTreeIter       *iter,
                              gpointer           data)
{
	DownloadNode* dnode;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);
	download_node_lock (dnode);
	g_object_set (cell, "text", dnode->filename, NULL);
	download_node_unlock (dnode);
}

static void col_set_completed (GtkTreeViewColumn *tree_column,
                               GtkCellRenderer   *cell,
                               GtkTreeModel      *model,
                               GtkTreeIter       *iter,
                               gpointer           data)
{
	DownloadNode* dnode;
	gchar*  string = NULL;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);

	if (dnode->total_size)
		string = dtoa_unit (dnode->completed_size, "");

	g_object_set (cell, "text", string, NULL);
	g_free (string);
}

static void col_set_total (GtkTreeViewColumn *tree_column,
                           GtkCellRenderer   *cell,
                           GtkTreeModel      *model,
                           GtkTreeIter       *iter,
                           gpointer           data)
{
	DownloadNode* dnode;
	gchar*  string = NULL;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);

	if (dnode->total_size)
		string = dtoa_unit (dnode->total_size, "");

	g_object_set (cell, "text", string, NULL);
	g_free (string);
}

static void col_set_percent (GtkTreeViewColumn *tree_column,
                             GtkCellRenderer   *cell,
                             GtkTreeModel      *model,
                             GtkTreeIter       *iter,
                             gpointer           data)
{
	DownloadNode* dnode;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);

	if (dnode->total_size && dnode->state < DOWNLOAD_STATE_COMPLETED) {
		gchar*  string = g_strdup_printf ("%.*f%c", 1, dnode->percent, '%');

		g_object_set (cell, "visible", 1, NULL);
		g_object_set (cell, "value", (gint)dnode->percent, NULL);
		g_object_set (cell, "text", string, NULL);
		g_free (string);
	}
	else {
		g_object_set (cell, "visible", 0, NULL);
		g_object_set (cell, "value", 0, NULL);
		g_object_set (cell, "text", "", NULL);
	}
}

static void col_set_speed (GtkTreeViewColumn *tree_column,
                           GtkCellRenderer   *cell,
                           GtkTreeModel      *model,
                           GtkTreeIter       *iter,
                           gpointer           data)
{
	DownloadNode* dnode;
	gchar*  string = NULL;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);

	if (dnode->total_size && dnode->state == DOWNLOAD_STATE_ACTIVE)
		string = dtoa_unit (dnode->speed, "/s");

	g_object_set (cell, "text", string, NULL);
	g_free (string);
}

static void col_set_retry (GtkTreeViewColumn *tree_column,
                           GtkCellRenderer   *cell,
                           GtkTreeModel      *model,
                           GtkTreeIter       *iter,
                           gpointer           data)
{
	DownloadNode* dnode;
	gchar*  string = NULL;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);

	if (dnode->total_size || dnode->retry_times)
		string = g_strdup_printf ("%d", dnode->retry_times);

	g_object_set (cell, "text", string, NULL);
	g_free (string);
}

static void col_set_url (GtkTreeViewColumn *tree_column,
                         GtkCellRenderer   *cell,
                         GtkTreeModel      *model,
                         GtkTreeIter       *iter,
                         gpointer           data)
{
	DownloadNode* dnode;

	gtk_tree_model_get (model, iter, 0, &dnode, -1);
	download_node_lock (dnode);
	g_object_set (cell, "text", dnode->url, NULL);
	download_node_unlock (dnode);
}

GtkTreeView* download_list_view_new ()
{
	GtkTreeView*       tview;
	GtkTreeSelection*  selection;
	GtkCellRenderer*   renderer;
	GtkCellRenderer*   renderer_progress;
	GtkTreeViewColumn* column;

	tview = (GtkTreeView*)gtk_tree_view_new ();
	selection = gtk_tree_view_get_selection (tview);
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);

	state_icons_render ((GtkWidget*)tview);

	// column filename
	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("Filename"));
	renderer = gtk_cell_renderer_pixbuf_new ();
	gtk_tree_view_column_pack_start (column, renderer, FALSE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_icon,
	                                         NULL, NULL);
	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_filename,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 120);
	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_append_column (tview, column);

	// column completed
	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "xalign", 1.0, NULL);
	gtk_tree_view_column_set_title (column, _("Completed"));
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_completed,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 70);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_alignment (column, 1.0);
	gtk_tree_view_append_column (tview, column);

	// column total
	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("Total"));
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_total,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 70);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_alignment (column, 1.0);
	gtk_tree_view_append_column (tview, column);

	// column percent
	column = gtk_tree_view_column_new ();
	renderer_progress = gtk_cell_renderer_progress_new ();
	gtk_tree_view_column_set_title (column, _("%"));
	gtk_tree_view_column_pack_start (column, renderer_progress, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer_progress,
	                                         (GtkTreeCellDataFunc)col_set_percent,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 50);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_alignment (column, 1.0);
	gtk_tree_view_append_column (tview, column);

	// columns speed
	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("Speed"));
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_speed,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 80);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_alignment (column, 1.0);
	gtk_tree_view_append_column (tview, column);

	// column retries
	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("Retry"));
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_retry,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 40);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_alignment (column, 1.0);
	gtk_tree_view_append_column (tview, column);

	// column url
	renderer = gtk_cell_renderer_text_new ();
	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("URL"));
//	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column,
	                                         renderer,
	                                         (GtkTreeCellDataFunc)col_set_url,
	                                         NULL, NULL);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 80);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_append_column (tview, column);
	g_object_set (tview, "fixed-height-mode", TRUE, NULL);

	return tview;
}

void download_list_view_column_set_visible (GtkTreeView* tview, int column_index, gboolean visible)
{
	GtkTreeViewColumn* column = gtk_tree_view_get_column (tview, column_index);

	gtk_tree_view_column_set_visible (column, visible);
}

void download_list_view_set (GtkTreeView* tview, ViewSetting* vs)
{
	GtkTreeViewColumn* column;

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_FILENAME);
	gtk_tree_view_column_set_visible (column, vs->download.filename.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.filename.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_COMPLETED);
	gtk_tree_view_column_set_visible (column, vs->download.completed.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.completed.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_TOTAL);
	gtk_tree_view_column_set_visible (column, vs->download.total.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.total.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_PERCENT);
	gtk_tree_view_column_set_visible (column, vs->download.percent.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.percent.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_SPEED);
	gtk_tree_view_column_set_visible (column, vs->download.speed.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.speed.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_RETRY);
	gtk_tree_view_column_set_visible (column, vs->download.retry.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.retry.width);

	column = gtk_tree_view_get_column (tview, DOWNLOAD_LIST_VIEW_URL);
	gtk_tree_view_column_set_visible (column, vs->download.url.visible);
	gtk_tree_view_column_set_min_width (column, vs->download.url.width);
}

